package cn.siriusbot.siriuspro.bot.plugin;

import cn.siriusbot.siriuspro.bot.BotApi;
import cn.siriusbot.siriuspro.bot.application.SiriusApplicationInfo;
import cn.siriusbot.siriuspro.bot.plugin.database.PlugInDatabaseInfo;
import cn.siriusbot.siriuspro.bot.pojo.event.BotEventMessage;
import cn.siriusbot.siriuspro.error.MsgException;
import cn.siriusbot.siriuspro.web.R.R;
import cn.siriusbot.siriuspro.web.pojo.BotHttpRequest;
import lombok.extern.log4j.Log4j2;
import org.springframework.web.context.request.async.DeferredResult;

import java.util.List;
import java.util.UUID;
import java.util.concurrent.CopyOnWriteArrayList;

/**
 * 钩子插件
 */
@Log4j2
public class HookPlugInClient extends PlugInDatabaseInfo implements PlugInClient {

    private final String uuid;
    SiriusApplicationInfo info;

    int cacheMax = 1024;    // 最大缓存为1024条消息

    List<String> sendList = new CopyOnWriteArrayList<>();    // 待发送列表
    long time;  // 推送时间戳

    BotApi botApi;

    /**
     * 异步钩子
     */
    private DeferredResult<String> result;

    public HookPlugInClient(SiriusApplicationInfo info, BotApi botApi) {
        this.info = info;
        this.uuid = UUID.randomUUID().toString();
        this.time = 0;
        this.botApi = botApi;
        super.updateInfo();
    }

    /**
     * 生成一个唯一的uuid作为键
     */
    @Override
    public String getUuid() {
        return uuid;
    }

    /**
     * 插件唯一id
     */
    @Override
    public String getPackageName() {
        return info.getPackageName();
    }

    /**
     * 插件详细
     */
    @Override
    public SiriusApplicationInfo getInfo() {
        return info;
    }


    /**
     * 上次响应时间
     */
    long timeMillis = 0;

    /**
     * 推送事件
     *
     * @param botId   机器人id
     * @param message 事件对象
     */
    @Override
    public void putEvent(String botId, BotEventMessage message) {
        timeMillis = System.currentTimeMillis();
        if (result == null || result.isSetOrExpired() && timeMillis - time > 30000) {
            // 钩子不可用后超时5秒清空缓存队列
            // 5秒以上Hook超时，不继续记录
            if (sendList.size() > 0) {
                sendList.clear();
            }
            return;
        }
        sendList.add(message.getMessage());
        putHook();  // 推送到钩子
    }

    /**
     * 推送到钩子
     */
    private void putHook() {
        // 检测钩子是否可用
        if (result.isSetOrExpired()) {
            return;
        }
        if (sendList.isEmpty()) {
            return;
        }
        R r = new R()
                .setCode(0)
                .setMsg(null)
                .setData(sendList);
        if (result.setResult(r.toString())) {
            log.info("[hook] 推送消息到钩子成功");
            sendList.clear();
            return;
        }
    }

    /**
     * 插件web请求处理
     *
     * @param request
     * @return R对象
     */
    @Override
    public R webPost(BotHttpRequest request) {
        return new R();
    }

    /**
     * 设置钩子
     */
    public void setHook(DeferredResult<String> result) {
        timeMillis = System.currentTimeMillis();
        if (this.result == null) {
            this.time = System.currentTimeMillis();
            this.result = result;
            putHook();  // 推送到钩子
            return;
        }
        // 检测之前的钩子是否不在可用
        if (this.result.isSetOrExpired()) {
            this.result = result;
            this.time = System.currentTimeMillis();
            putHook();  // 推送到钩子
            return;
        }
        throw new MsgException(500, "当前应用已经请求了一个钩子!");
    }

    /**
     * 获取插件的BotApi
     *
     * @return BotApi对象
     */
    @Override
    public BotApi getBotApi() {
        return botApi;
    }
}
